home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / DJGPP / CBGRX103.ZIP / contrib / libgrx / src / colors.c < prev    next >
Text File  |  1993-12-06  |  10KB  |  411 lines

  1. /**
  2.  ** COLORS.C
  3.  **
  4.  **  Copyright (C) 1992, Csaba Biegl
  5.  **    820 Stirrup Dr, Nashville, TN, 37221
  6.  **    csaba@vuse.vanderbilt.edu
  7.  **
  8.  **  This file is distributed under the terms listed in the document
  9.  **  "copying.cb", available from the author at the address above.
  10.  **  A copy of "copying.cb" should accompany this file; if not, a copy
  11.  **  should be available from where this file was obtained.  This file
  12.  **  may not be distributed without a verbatim copy of "copying.cb".
  13.  **  You should also have received a copy of the GNU General Public
  14.  **  License along with this program (it is in the file "copying");
  15.  **  if not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  16.  **  Cambridge, MA 02139, USA.
  17.  **
  18.  **  This program is distributed in the hope that it will be useful,
  19.  **  but WITHOUT ANY WARRANTY; without even the implied warranty of
  20.  **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21.  **  GNU General Public License for more details.
  22.  **/
  23.  
  24. #include "grx.h"
  25. #include "libgrx.h"
  26. #include "interrup.h"
  27. #include "gmalloc.h"
  28. #include "reg8514a.h"
  29.  
  30. #include <string.h>
  31. #include <stdlib.h>
  32.  
  33.  
  34. typedef struct {
  35.     unsigned int  n:6;
  36.     unsigned int  state:2;        /* 0=free, 1=shared, 2=writable */
  37.     unsigned char r;
  38.     unsigned char g;
  39.     unsigned char b;
  40. } color;
  41.  
  42. #define C_FREE        0        /* free color */
  43. #define C_SHARED    1        /* shared (by GrAllocColor) */
  44. #define C_WRITABLE    2        /* writable (by GrAllocCell) */
  45.  
  46. #define KEEPBITS(v,n)                        \
  47.     v = ((v += (0x80 >> n)) > 0xff) ?                \
  48.     (0xff ^ (0xff >> n)) :                    \
  49.     (v & (0xff ^ (0xff >> n)))
  50.  
  51.  
  52. static color *colortable = NULL;    /* color info table */
  53. static int maxused;            /* max used index in table */
  54. static int freecolors;            /* number of free colors */
  55. static int whitecolor;            /* index of white color */
  56. static int RGBmode;            /* set when in RGB mode */
  57. static int lastcolors = -1;        /* # of colors last initted to */
  58.  
  59. #define init_done()    (lastcolors == _GrNumColors)
  60.  
  61. static void setcolor(int c,int r,int g,int b)
  62. {
  63.     REGISTERS regs;
  64.  
  65.     switch(_GrAdapterType) {
  66.       case GR_EGA:
  67.         regs.r_ax = 0x1000;
  68.         regs.r_bx = c & 0x0f;
  69.         regs.r_bx |= ((r & 0x40) << 7) | ((r & 0x80) << 3);
  70.         regs.r_bx |= ((g & 0x40) << 6) | ((g & 0x80) << 2);
  71.         regs.r_bx |= ((b & 0x40) << 5) | ((b & 0x80) << 1);
  72.         int10(®s);
  73.         break;
  74.       case GR_VGA:
  75.       case GR_S3:
  76.         if(_GrNumColors == 16) {
  77.         regs.r_ax = 0x1000;
  78.         regs.r_bx = (c & 0x0f) | ((c & 0x0f) << 8);
  79.         int10(®s);
  80.         }
  81. #ifdef __GNUC__
  82.         asm volatile(
  83.         "cli                                \n"
  84.         "movl    %0,%%eax                   \n"
  85.         "movl    $0x3c8,%%edx               \n"
  86.         "outb    %%al,%%dx                  \n"
  87.         "inb     $0x80,%%al                 \n"
  88.         "incl    %%edx                      \n"
  89.         "movl    %1,%%eax                   \n"
  90.         "shrb    $2,%%al                    \n"
  91.         "outb    %%al,%%dx                  \n"
  92.         "inb     $0x80,%%al                 \n"
  93.         "movl    %2,%%eax                   \n"
  94.         "shrb    $2,%%al                    \n"
  95.         "outb    %%al,%%dx                  \n"
  96.         "inb     $0x80,%%al                 \n"
  97.         "movl    %3,%%eax                   \n"
  98.         "shrb    $2,%%al                    \n"
  99.         "outb    %%al,%%dx                  \n"
  100.         "sti                                \n"
  101.         : /* NOTHING */
  102.         : "g" (c), "g" (r), "g" (g), "g" (b)
  103.         : "ax", "dx"
  104.         );
  105. #elif defined(__TURBOC__)
  106.         disable();
  107.         outportb(0x3c8,c);
  108.         inportb(0x80);
  109.         outportb(0x3c9,(r >> 2));
  110.         inportb(0x80);
  111.         outportb(0x3c9,(g >> 2));
  112.         inportb(0x80);
  113.         outportb(0x3c9,(b >> 2));
  114.         enable();
  115. #else
  116.         regs.r_ax = 0x1010;
  117.         regs.r_bx = c & 0xff;
  118.         regs.r_dx = ((r & 0xfc) << 6);
  119.         regs.r_cx = ((g & 0xfc) << 6) | ((b & 0xfc) >> 2);
  120.         int10(®s);
  121. #endif
  122.         break;
  123.       case GR_8514A:
  124.         WaitQueue(4);
  125.         outp(DAC_W_INDEX,c);
  126.         outp(DAC_DATA,(r >> 2));
  127.         outp(DAC_DATA,(g >> 2));
  128.         outp(DAC_DATA,(b >> 2));
  129.         break;
  130.     }
  131.     colortable[c].r = r;
  132.     colortable[c].g = g;
  133.     colortable[c].b = b;
  134. }
  135.  
  136. static int initcolors(void)
  137. {
  138.     int whitevalue;
  139.  
  140.     if((_GrCurrentMode >= GR_320_200_graphics) && !init_done()) {
  141.        switch(_GrNumColors) {
  142. #if (GRXPLANES & 16)
  143.           case 32768:
  144. #endif
  145.           case 2:
  146.         whitecolor = _GrNumColors - 1;
  147.         freecolors = 0;
  148.         RGBmode = TRUE;
  149.         maxused = 0;
  150.         break;
  151.           case 256:
  152.           case 16:
  153.         whitecolor = 15;
  154.         whitevalue = (_GrAdapterType == GR_EGA) ? 0xc0 : 0xfc;
  155.         if((_GrNumColors > lastcolors) && (colortable != NULL)) {
  156.             _GrFree(colortable);
  157.             colortable = NULL;
  158.         }
  159.         if(colortable == NULL) {
  160.             colortable = _GrMalloc(sizeof(color) * _GrNumColors);
  161.             if(colortable == NULL) return(FALSE);
  162.         }
  163.         memset(colortable,0,(sizeof(color) * _GrNumColors));
  164.         colortable[0].state = C_SHARED;
  165.         setcolor(0,0,0,0);
  166.         colortable[whitecolor].state = C_SHARED;
  167.         setcolor(whitecolor,whitevalue,whitevalue,whitevalue);
  168.         freecolors = _GrNumColors - 2;
  169.         maxused = whitecolor + 1;
  170.         RGBmode = FALSE;
  171.         break;
  172.         }
  173.         lastcolors = _GrNumColors;
  174.     }
  175.     return(init_done() ? TRUE : FALSE);
  176. }
  177.  
  178. void GrResetColors(void)
  179. {
  180.     lastcolors = (lastcolors >= _GrNumColors) ? (_GrNumColors + 1) : (-1);
  181.     initcolors();
  182. }
  183.  
  184. void GrRefreshColors(void)
  185. {
  186.     color *c;
  187.     int n;
  188.  
  189.     if(lastcolors != _GrNumColors)
  190.         initcolors();
  191.     else for(n = 0,c = colortable; n < maxused; n++,c++)
  192.         if(c->state != C_FREE) setcolor(n,c->r,c->g,c->b);
  193. }
  194.  
  195. void GrSetRGBcolorMode(void)
  196. {
  197.     color *c;
  198.     int n;
  199.  
  200.     if((init_done() || initcolors()) && !RGBmode &&
  201.        ((_GrAdapterType == GR_VGA) ||
  202.         (_GrAdapterType == GR_8514A) ||
  203.         (_GrAdapterType == GR_S3)) &&
  204.        (_GrNumColors == 256)) {
  205.         for(n = 0,c = colortable; n < 256; n++,c++) {
  206.         c->state = C_SHARED;
  207.         c->n = 1;
  208.         setcolor(n,(n & 0xe0),((n << 3) & 0xe0),((n << 6) & 0xc0));
  209.         }
  210.         freecolors = 0;
  211.         whitecolor = 255;
  212.         RGBmode = TRUE;
  213.         maxused = 256;
  214.     }
  215. }
  216.  
  217. int GrNumColors(void)
  218. {
  219.     return(_GrNumColors);
  220. }
  221.  
  222. int GrNumFreeColors(void)
  223. {
  224.     if(!init_done()) initcolors();
  225.     return(freecolors);
  226. }
  227.  
  228. int GrWhite(void)
  229. {
  230.     return((init_done() || initcolors()) ? whitecolor : GrNOCOLOR);
  231. }
  232.  
  233. int GrBlack(void)
  234. {
  235.     return((init_done() || initcolors()) ? 0 : GrNOCOLOR);
  236. }
  237.  
  238. int GrAllocColor(int r,int g,int b)
  239. {
  240.     color *c;
  241.     int err,minerr;
  242.     int n,free = (-1);
  243.  
  244.     if(!init_done() && !initcolors()) return(GrNOCOLOR);
  245.     if(RGBmode) switch(_GrNumColors) {
  246. #if (GRXPLANES & 16)
  247.       case 32768:
  248.         KEEPBITS(r,5);
  249.         KEEPBITS(g,5);
  250.         KEEPBITS(b,5);
  251.         return((r << 7) | (g << 2) | (b >> 3));
  252. #endif
  253.       case 256:
  254.         KEEPBITS(r,3);
  255.         KEEPBITS(g,3);
  256.         KEEPBITS(b,2);
  257.         return(r | (g >> 3) | (b >> 6));
  258.       case 2:
  259.         return(((r*30 + g*59 + b*11) >= 128*100) ? 1 : 0);
  260.       default:
  261.         return(GrNOCOLOR);
  262.     }
  263.     switch(_GrAdapterType) {
  264.       case GR_EGA:
  265.         KEEPBITS(r,2);
  266.         KEEPBITS(g,2);
  267.         KEEPBITS(b,2);
  268.         break;
  269.       case GR_VGA:
  270.       case GR_8514A:
  271.       case GR_S3:
  272.         KEEPBITS(r,6);
  273.         KEEPBITS(g,6);
  274.         KEEPBITS(b,6);
  275.         break;
  276.       default:
  277.         return(GrNOCOLOR);
  278.     }
  279.     for(n = 0,c = colortable; n < maxused; n++,c++) {
  280.         switch(c->state) {
  281.           case C_SHARED:
  282.         if((c->r != r) || (c->g != g) || (c->b != b)) break;
  283.         c->n++;
  284.         return(n);
  285.           case C_FREE:
  286.         free = n;
  287.         break;
  288.         }
  289.     }
  290.     if((free < 0) && (maxused < _GrNumColors))
  291.         free = maxused++;
  292.     if(free >= 0) {
  293.         colortable[free].state = C_SHARED;
  294.         colortable[free].n = 1;
  295.         setcolor(free,r,g,b);
  296.         freecolors--;
  297.         return(free);
  298.     }
  299.     minerr = 3*32*32;
  300.     for(n = 0,c = colortable; n < _GrNumColors; n++,c++) {
  301.         if(c->state == C_SHARED) {
  302.         err = ((c->r - r) >> 2) * (c->r - r) +
  303.               ((c->g - g) >> 2) * (c->g - g) +
  304.               ((c->b - b) >> 2) * (c->b - b);
  305.         if(err <= minerr) {
  306.             minerr = err;
  307.             free = n;
  308.         }
  309.         }
  310.     }
  311.     if(free >= 0) {
  312.         colortable[free].n++;
  313.         return(free);
  314.     }
  315.     return(GrNOCOLOR);
  316. }
  317.  
  318. int GrAllocCell(void)
  319. {
  320.     int n,free = (-1);
  321.  
  322.     if((init_done() || initcolors()) && !RGBmode && (freecolors > 0)) {
  323.         for(n = 0; n < maxused; n++) {
  324.         if(colortable[n].state == C_FREE) {
  325.             free = n;
  326.             break;
  327.         }
  328.         }
  329.         if(free < 0) free = maxused++;
  330.         colortable[free].state = C_WRITABLE;
  331.         colortable[free].n = 1;
  332.         freecolors--;
  333.         return(free);
  334.     }
  335.     return(GrNOCOLOR);
  336. }
  337.  
  338. void GrFreeColor(int n)
  339. {
  340.     color *c;
  341.  
  342.     if(init_done() && !RGBmode &&
  343.        ((unsigned)n < (unsigned)_GrNumColors) &&
  344.        ((c = &colortable[n])->state != C_FREE)) {
  345.         if(c->n > 0)  c->n--;
  346.         if(c->n == 0) c->state = C_FREE;
  347.     }
  348. }
  349.  
  350. void GrSetColor(int n,int r,int g,int b)
  351. {
  352.     color *c;
  353.  
  354.     if((init_done() || initcolors()) && !RGBmode &&
  355.        ((unsigned)n < (unsigned)_GrNumColors)) {
  356.         c = &colortable[n];
  357.         switch(c->state) {
  358.           case C_SHARED:
  359.         if(c->n > 0) return;
  360.         break;
  361.           case C_FREE:
  362.         if(n >= maxused) maxused = n + 1;
  363.         freecolors--;
  364.         break;
  365.         }
  366.         c->state = C_WRITABLE;
  367.         c->n = 1;
  368.         switch(_GrAdapterType) {
  369.           case GR_EGA:
  370.         KEEPBITS(r,2);
  371.         KEEPBITS(g,2);
  372.         KEEPBITS(b,2);
  373.         break;
  374.           case GR_VGA:
  375.         KEEPBITS(r,6);
  376.         KEEPBITS(g,6);
  377.         KEEPBITS(b,6);
  378.         break;
  379.         }
  380.         setcolor(n,r,g,b);
  381.     }
  382. }
  383.  
  384. void GrQueryColor(int n,int *r,int *g,int *b)
  385. {
  386.     color *c;
  387.  
  388.     if(init_done() && ((unsigned)n < (unsigned)_GrNumColors)) {
  389.         if(colortable == NULL) switch(_GrNumColors) {
  390. #if (GRXPLANES & 16)
  391.           case 32768:
  392.         *r = (n >> 7) & 0xf8;
  393.         *g = (n >> 2) & 0xf8;
  394.         *b = (n << 3) & 0xf8;
  395.         return;
  396. #endif
  397.           case 2:
  398.         *r = *g = *b = (n ? 255 : 0);
  399.         return;
  400.           default:
  401.         *r = *g = *b = 0;
  402.         return;
  403.         }
  404.         c = &colortable[n];
  405.         *r = c->r;
  406.         *g = c->g;
  407.         *b = c->b;
  408.     }
  409. }
  410.  
  411.